/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package continuity;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.StringTokenizer;
import org.jfree.date.SpreadsheetDate;

/**
 *
 * @author ndrew
 */
public class Proto {
    private static ProtoInterpreter Interpreter; 
    private static boolean mainLoop=true;
    private Game game;
    private Clock clock;
    private Character charcter;
    private Character charcter2;
    
    
    private HashMap<String, Level> LevelMap;
    private HashMap<String, LevelItem> LevelItemMap;
    private HashMap<String, Sprite> SpriteMap;
    
    // peldanyositott objektum init
    
    public void init() {
        // itt hozzuk letre az interpretert, 
        // hogy at tudjunk neki adni egy peldanyt
        Interpreter = new ProtoInterpreter(this);
        LevelMap = new HashMap<String, Level>();
        LevelItemMap = new HashMap<String, LevelItem>();
        SpriteMap = new HashMap<String, Sprite>();
    }
    
    //alkalmazas belepesi pontja
    public static void main(String[] args) {
            Proto app = new Proto();
            app.init();
            InputStream input = System.in;
	    BufferedReader instream = new BufferedReader(
                    new InputStreamReader(input));
            //alkamazas fociklus
            // addig fut, amig quitet nem hivunk
            while (mainLoop) {
              try {
                    //kiirjuk a promptot
                    System.out.print(">");
                    //beolvassuk a bementet es atadjuk az interpreternek
                    //aki a peldanyositott objektumon visszahivja a megfelelo
                    // fuggvenyt
                    String inputLine = instream.readLine();
                    Interpreter.interpret(inputLine);
               }
               catch (Exception e) {
                            System.out.println("  " + e.toString());
               }
            }
    }
    
    
    // kilep az alkalmazasbol, megszakitja a 
    // main loopot
    public void quit() {
        mainLoop = false;
        for(String s: SpriteMap.keySet()) {
            Sprite i=SpriteMap.get(s);
            output(i.getName(), i.getClass().toString(), "Destroyed","", "");
        }
       for(String s: LevelItemMap.keySet()) {
            LevelItem i=LevelItemMap.get(s);
            output(i.getName(), i.getClass().toString(), "Destroyed","", "");
        }
        for(String s: LevelMap.keySet()) {
            Level i=LevelMap.get(s);
            output(i.getName(), i.getClass().toString(), "Destroyed","", "");
        }
                
    }
    
    //m,egadott szamu tick generalasa
    public void tick(int number) {
            clock.start(number);
            
    }
    
    // jatek alapobjektumainak keszitese
    public void loadGame(String file) {
        game = new Game("game");
        clock = game.getClock();
        //charcter = game.getCharacter();
        //charcter2 = game.getCharacter2();
        //SpriteMap.put(game.getCharacter().getName(),game.getCharacter() );
        //SpriteMap.put(game.getCharacter2().getName(),game.getCharacter2() );
        
        // palyak es egyebek olvasasa
        try {
            BufferedReader instream = new BufferedReader(
                new FileReader(file));
            String line = instream.readLine();
            int levels = Integer.parseInt(line.trim());
            while( levels-- > 0 ) {
                line = instream.readLine();
                StringTokenizer tokenizer = new StringTokenizer(line, "   ");
                String name = tokenizer.nextToken().trim();
                int LevelItems = Integer.parseInt(tokenizer.nextToken().trim());
                createLevel(name);
                while( LevelItems-- > 0 ) {
                    line = instream.readLine();
                    tokenizer = new StringTokenizer(line, "   ");
                    String itemName = tokenizer.nextToken().trim();
                    int Sprites = Integer.parseInt(tokenizer.nextToken()
                            .trim());
                    int x = Integer.parseInt(tokenizer.nextToken().trim());
                    int y = Integer.parseInt(tokenizer.nextToken().trim());
                    createLevelItem(itemName, x, y);
                    addLevelItem(name, itemName);
                     while( Sprites-- > 0 ) {
                        line = instream.readLine();
                        tokenizer = new StringTokenizer(line, "   ");
                        String spriteName = tokenizer.nextToken().trim();
                        String type = tokenizer.nextToken().trim();
                        x = Integer.parseInt(tokenizer.nextToken().trim());
                        y = Integer.parseInt(tokenizer.nextToken().trim());
                        int width;
                        int height;
                        
                        if(type.equals("w")) {
                            width = Integer.parseInt(tokenizer.nextToken()
                                    .trim());
                            height = Integer.parseInt(tokenizer.nextToken()
                                    .trim());
                            createSprite(type, x, y, spriteName,
                                new Object[] {width, height});
                        } else {
                        createSprite(type, x, y, spriteName,
                                null);
                        }
                        addSprite(itemName, spriteName);
                    }
                }
            }
        } catch(Exception e) {System.out.println(e.getMessage());}
	
    }
    
    public void setPeriod(int period) {
        clock.setPeriod(period);
    }
    // szintek listazasa
    public void showLevels() {
        System.out.println(LevelMap.size());
        for(String l: LevelMap.keySet()) {
            System.out.println(l.toString());
        }
    }
    public void showLevelItems(String level) {
        if(level.isEmpty()) {
            System.out.println(LevelItemMap.size());
            for(String l: LevelItemMap.keySet()) {
                System.out.println(l.toString());
            }
        }
        else if(LevelMap.containsKey(level)) {
            System.out.println(LevelMap.get(level).getSize());
            for( LevelItem[] i1 : LevelMap.get(level).getLevelItems()) {
                for(LevelItem i2 : i1) {
                    if(i2 != null) System.out.println(i2.getName());
                }
            }
        }
        else {
            System.out.println("A megadott nevvel nem letezik Level!"+level);
        }
    }
    public void showSprites(String name) {
        if(name.isEmpty()) {
            System.out.println(SpriteMap.size());
            for(String l: SpriteMap.keySet()) {
                System.out.println(l.toString());
        }
        } else if(LevelItemMap.containsKey(name)) {
            System.out.println(LevelItemMap.get(name).getSprites().size());
            for( Sprite i1 : LevelItemMap.get(name).getSprites()) {
                System.out.println(i1.getName());
            }
        }
        else {
            System.out.println("A megadott nevvel nem letezik LevelItem!");
        }
    }
    
    //elemek letrehozasara szolgalo fuggvenyek
    public void createLevel(String name) {
        // id a soron következő
        if(name.isEmpty()) name = String.valueOf(LevelMap.size()+1);
        // letrehozas
        Level l = new Level(name);
        //hozzaadas
        LevelMap.put(name, l);
        game.addLevel(l);
        output(name, l.getClass().toString(), "Created","", "");
    }
    // LevelItem letrehozasa
    public void createLevelItem(String name, int x, int y) {
        name =name.isEmpty() ? String.valueOf(LevelItemMap.size()+1) : name;
        LevelItem l = new LevelItem(name, x, y);
        LevelItemMap.put(name, l); 
    }
    //Sprite letrehozasa
    public void createSprite(String type, int x, int y, String name,
            Object[] params ) {
        Sprite s;
        //elvégezzük a szurest, hogy tudjuk, milyen objektumot hozunk letre
        if(type.equals("c")) {
            Object[] i = {new Point3d(x,y), name};
            //a game factoryjat hasznaljuk
            s=game.getFactory().createSprite(1, i);
            if(charcter==null) {
                //ha meg nincs karakterunk, beallitjuk
                charcter = (Character)s;
                game.setCharacter(charcter);
            }
            else if(charcter2==null) {
                //ha meg nincs masodlagos karakterunk, beallitjuk
                charcter2 = (Character)s;
                game.setCharacter2(charcter2);
            }
        } else if(type.equals("d")) {
            Object[] i = {new Point3d(x,y), name};
            s=game.getFactory().createSprite(2, i);
        } else if(type.equals("k")) {
            Object[] i = {new Point3d(x,y), name};
            s=game.getFactory().createSprite(3, i);
        } else {
            
            //ha negy egyezes sincs, akkor fal kell nekunk.
            Object[] i = {new Point3d(x,y), (Integer)params[0],
                (Integer)params[1], name};
            s=game.getFactory().createSprite(4, i);
        }
        name = name.isEmpty() ? String.valueOf(SpriteMap.size()+1) : name;
        SpriteMap.put(name, s);
    }
    // LevelItem hozzaadasa a LevelHez
    public void addLevelItem(String to, String what) {
        Level l = LevelMap.get(to);
        LevelItem i = LevelItemMap.get(what);
        l.addLevelItem(i);
        output(what, i.getClass().toString(), "Created",to, l.getClass().toString());
    }
    // Sprite hozzaadas a levelitemhez.
    public void addSprite(String to, String what) {
        LevelItem l = LevelItemMap.get(to);
        Sprite i = SpriteMap.get(what);
        l.addSprite(i);
        output(what, i.getClass().toString(), "Created",to, l.getClass().toString());
    }
    
    //aktualis nezet megszerzese
    public void getView() {
        System.out.println(game.getView());   
    }
    
    //view beallitasa
    public void changeView(int i) {
        game.changeView(i);
        
    }
    
    //jatekos iranyanak beallitasa
    public void setMoveDir(int dir, int player) {
        if(player == 1) {
            charcter.setDir(dir);
        }
        else {
            charcter2.setDir(dir);
        }
    }
    // a karakter sebességének beolvasása
    // opcióként választható, hogy melyiket válaszza
    public void setPlayerSpeed(int dir, int player) {
        if(player == 1) {
            charcter.setSpeed(dir);
        }
        else {
            charcter2.setSpeed(dir);
        }
    }
    // karakter mozgatása, mivel már 2 karakter van, válsztható, hogy 
    // melyik mozogjon
    public void playerMove(int player) {
        if(player == 1) {
            charcter.setMoveNext(true);
        }
        else {
            charcter2.setMoveNext(true);
        }
    }
    //üres elem mozgatása
    public void moveEmptyItem(int dir) {
        game.getActualLevel().moveEmptyItem(dir);
    }
    // teszt fájl betöltése
    public void loadTestFile(String file) {
       try {
            BufferedReader instream = new BufferedReader(
                new FileReader(file));
            String line;
            while( (line = instream.readLine()) != null ) {
                Interpreter.interpret(line);
            }
        } catch(Exception e) {System.out.println("kapufa");}
	
    }
    
    public static void output(String what, String type,
            String action, String on, String onType ) {
        
        System.out.print(what+":"+splitClassName(type)+":"+action+" ");
        if(!on.isEmpty() && !onType.isEmpty()) {
            System.out.print("on "+on+":"+splitClassName(onType));
        }
        System.out.println();
    }
    private static String splitClassName(String name) {
        String ret = name.replace("class ", "");
        ret = ret.replace("continuity.", "");
        return ret;
    }
    
    
    
}

